﻿using Ec.NETCoreFramework.Common.MQ;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
using System.Threading.Tasks;
using Ec.NETCoreFramework.Common.Core.Serializer;
using Ec.NETCoreFramework.Common.Plug.Core;

namespace Ec.NETCoreFramework.Common.Plug.MQService
{
	/// <summary>
	/// 消费端管理
	/// </summary>
    public class ConsumeManage
    {	
		/// <summary>
		/// 处理消费队列
		/// </summary>
		/// <param name="config"></param>
		public static void HandleConsumeMQ(AppConfig config)
        {
			var listDll = new List<TaskInterface>();
			var path = Path.Combine(Directory.GetCurrentDirectory(), "plandll"); ;
			var files = Directory.GetFiles(path).Where(f => f.Contains("MQ")).ToArray();

			// 记录当前文件信息和对象信息
			var fileInfolist = new Dictionary<string, TaskInterface>();
			var _AssemblyLoadContext = new AssemblyLoadContext(Guid.NewGuid().ToString("N"), true);
			foreach (var item in files)
			{
				var index = -1;
				if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
				{
					index = item.LastIndexOf("\\");
				}
				else
				{
					index = item.LastIndexOf("/");
				}

				var jobConfig = config.GetJob(item.Substring(index + 1));
				if (jobConfig == null|| jobConfig.Consumes==null) continue;
				using (var fs = new FileStream(item, FileMode.Open, FileAccess.Read))
				{

					var assembly = _AssemblyLoadContext.LoadFromStream(fs);//可以直接读数据库																		  

					var type = assembly.GetExportedTypes().Where((t) =>
					{
						return t.BaseType!=null&&t.BaseType.Name == typeof(TaskInterface).Name;
					}).FirstOrDefault();
					foreach (var q in jobConfig.Consumes)
					{
						var fileInfo = new FileInfo(item);
						string fileName = fileInfo.Name + "-" + q.UnionId;
						TaskInterface currentJob = Activator.CreateInstance(type) as TaskInterface;

						q.Secret = config.ReqAppSecret.Secret;
						q.AppId = config.ReqAppSecret.AppId;
						//设置队列名称
						currentJob.SetConsumeConfig(ProtoBufSerializer.Serializeby(q));
						//最后修改时间
						currentJob.FileInfoLastTime = fileInfo.LastWriteTime;
						fileInfolist.Add(fileName, currentJob);

						// 添加任务  
						if (!dicConsume.ContainsKey(fileName))
						{
							Add(fileName, currentJob, config.MQConf, jobConfig);

						}
						else
						{
							Remove(fileName, fileInfo.LastWriteTime, currentJob, config.MQConf, jobConfig);
						}
					}
				}

			}
			var dllkeys = dicConsume.Keys.ToArray();

			for (int i = dllkeys.Length - 1; i >= 0; i--)
			{
				if (!fileInfolist.Keys.Contains(dllkeys[i]))
				{
					//业务的dll 
					Remove(dllkeys[i]);
				}
			}
		}
		/// <summary>
		/// 消费端维护
		/// </summary>
		public static Dictionary<string, MsgConsume> dicConsume = new Dictionary<string, MsgConsume>();
		/// <summary>
		/// 加入
		/// </summary>
		/// <param name="key"></param>
		/// <param name="currentJob"></param>
		/// <param name="mqConfig"></param>
		/// <param name="jobConfig"></param>
		public static void Add(string key, TaskInterface currentJob, MQConfig mqConfig, JobConfig jobConfig)
		{

			//var task = new Task(() =>
			//{
			//	var msgConsume = new MsgConsume(mqConfig.Server, mqConfig.UserName, mqConfig.Pwd);
			//	dicConsume.Add(key, msgConsume);
			//	msgConsume.Consume(currentJob);
			//});
			//task.Start();
			var msgConsume = new MsgConsume(mqConfig.Server, mqConfig.UserName, mqConfig.Pwd, jobConfig.VirtualHost);
			dicConsume.Add(key, msgConsume);
			msgConsume.Consume(currentJob);

		}
		 /// <summary>
		 /// 移除
		 /// </summary>
		 /// <param name="key"></param>
		 /// <param name="lastWriteTime"></param>
		 /// <param name="currentJob"></param>
		 /// <param name="mqConfig"></param>
		 /// <param name="jobConfig"></param>
		public static void Remove(string key, DateTime lastWriteTime, TaskInterface currentJob, MQConfig mqConfig, JobConfig jobConfig)
		{
			if (dicConsume.ContainsKey(key))
			{
				//判断时间
				if (lastWriteTime > dicConsume[key].taskInterface.FileInfoLastTime)
				{
					dicConsume[key].Close();
					dicConsume.Remove(key);
					Add(key, currentJob, mqConfig, jobConfig);
				}
				//如果假死，则删除
				if (!dicConsume[key].IsRunning())
				{
					dicConsume[key].Close();
					dicConsume.Remove(key);
				}
			}

		}
		/// <summary>
		/// 移除单个
		/// </summary>
		/// <param name="key"></param>
		public static void Remove(string key)
		{
			if (dicConsume.ContainsKey(key))
			{
				dicConsume[key].Close();
				dicConsume.Remove(key);
			}
		}
	}
}
